﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace UFrame
{
    /// <summary>
    /// 路径同一用 / 不然加载不出AB包资源
    /// 初始化流程
    /// 初始化全部的ma组件
    /// 下载检查 =》 加载AB包(可选) => 正常游戏
    /// 负责游戏初始化 
    /// </summary>
    public abstract class GameFrameWorkMa : MaMono<GameFrameWorkMa>
    {
        public Transform entity;
        public Transform effect;
        public Transform ui;
        public Transform main;

        private float initTime = 0f;
        private float initTimer = 6f; //4秒内必须初始化完毕

        /// <summary>
        /// 如何初始化主框架组件
        /// </summary>
        public bool isQueueInitMa = false;

        /// <summary>
        /// 如何初始化子系统组件
        /// </summary>
        private bool isQueueInitSystem = false;


        [SerializeField] public List<IMa> maList = new List<IMa>();
        [SerializeField] public List<IMa> systemMaList = new List<IMa>();


        private Dictionary<string, GameObject> systemDic = new Dictionary<string, GameObject>();

        protected override void Awake()
        {
            base.Awake();
            DontDestroyOnLoad(this.gameObject);

            effect = CreateChild(ref main, "effect"); //初始化节点
            entity = CreateChild(ref main, "entity");
            ui = CreateChild(ref main, "ui");
            if (main == null)
                main = transform;
            
            OnAwakeAddMa();

            if (!isQueueInitMa)
            {
                var list = FindObjectsOfType<MonoBehaviour>();
                foreach (var item in list)
                {
                    if (item is IMa)
                    {
                        IMa a = item as IMa;
                        maList.Add(item as IMa);
                        a.Init();
                    }
                }
            }
        }

        private Transform CreateChild(ref Transform go, string goName)
        {
            var newGo = new GameObject().transform;
            newGo.name = goName;
            if (go == null)
            {
                newGo.SetParent(transform);
            }
            else
            {
                newGo.SetParent(go);
            }

            return newGo;
        }


        public void AddMB<T>(string name) where T : MonoBehaviour
        {
            T t = null;
            if (systemDic.ContainsKey(name))
            {
                t = systemDic[name].AddComponent<T>();
            }
            else
            {
                GameObject go = new GameObject();
                DontDestroyOnLoad(go);
                t = go.AddComponent<T>();
                systemDic.Add(name, go);
            }

            if (t is IMa)
            {
                systemMaList.Add(t as IMa);
            }
        }

        public void RemoveMB<T>(string name) where T : MonoBehaviour
        {
            if (!systemDic.ContainsKey(name))
            {
                return;
            }

            var t = systemDic[name].GetComponent<T>();
            Destroy(t); //删除某一个组件
        }

        public void PrepareSystem(bool isQueueInit)
        {
            isQueueInitSystem = isQueueInit;
            systemMaList.Clear();
        }

        public void CheckSystemInit(Action onComplete)
        {
            StartCoroutine(CheckInit(systemMaList, onComplete));
        }

        /// <summary>
        /// 子类会初始化的一些组件
        /// </summary>
        protected virtual void OnAwakeAddMa()
        {
        }

        /// <summary>
        /// 盘子脸专用方法
        /// </summary>
        public virtual void AddPLMa()
        {
            AddComponentOne<EffectMa>(effect.gameObject);
            AddComponentOne<GameSpeedMB>(main.gameObject);
            //AddComponentOne<UILaunchMa>(ui.gameObject);
        }

        public void AddComponentOne<T>(GameObject go = null) where T : MonoBehaviour
        {
            if (go == null)
            {
                go = gameObject;
            }

            T t = null;
            if (go.GetComponent<T>() == null)
            {
                t = go.AddComponent<T>();
            }

            if (t is IMa && isQueueInitMa)
            {
                maList.Add(t as IMa);
            }
        }

        /// <summary>
        /// 初始化完毕回调
        /// </summary>
        protected abstract void OnUFrameInit();


        private void OnUFrameInitComplete()
        {
            //PLDebug.Log("Ma Init Complete");
            OnUFrameInit();
            EventMa.Notify(UFrameInitArgs.EventId);
        }

        protected void Start()
        {
            StartCoroutine(CheckInit(maList, OnUFrameInitComplete));
        }

        private IEnumerator CheckInit(List<IMa> list, Action onComplete = null)
        {
            while (true)
            {
                yield return new WaitForSeconds(0.5f);

                if (isQueueInitMa)
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        IMa ma = list[i];
                        initTime = 0f;
                        if (!isInit)
                        {
                            ma.Init();
                        }

                        while (true)
                        {
                            yield return new WaitForSeconds(0.5f);

                            if (ma.IsInit)
                            {
                                break;
                            }

                            initTime += 0.5f;
                            if (initTime >= initTimer)
                            {
                                PLDebug.LogError("not init Ma :" + ma.IsInit);
                                break;
                            }
                        }
                    }
                }
                else
                {
                    bool result = true;
                    for (int i = 0; i < list.Count; i++)
                    {
                        if (list[i].IsInit == false)
                        {
                            result = false;
                            break;
                        }
                    }

                    if (result)
                    {
                        break;
                    }

                    initTime += 0.5f;
                    if (initTime >= initTimer)
                    {
                        initTime = 0;
                        for (int i = 0; i < list.Count; i++)
                        {
                            if (!list[i].IsInit)
                            {
                                PLDebug.LogError("not init Ma :" + list[i].IsInit);
                            }
                        }

                        break;
                    }
                }
            }

            if (onComplete != null)
            {
                onComplete();
            }
        }
        
    }
}